#include"mystdio.h"
//系统调用的三个头文件
#include<sys/types.h>
#include<sys/stat.h>
#include<fcntl.h>
#include<string.h>
#include<stdlib.h>
#include<unistd.h>


static MyFile *BuyFile(int fd,int flag)     //开辟新的File   static修饰表示只在本文件内有效
{
    MyFile *f = (MyFile*)malloc(sizeof(MyFile));
    if(f == NULL)   return NULL;
    f->bufferlen = 0;
    f->fileno = fd;
    f->flag = flag;
    f->flush_method = LINE_FLUSH;
    memset(f->outbuffer,0,sizeof(f->outbuffer));
    return f;
}


MyFile* MyFopen(const char* path,const char* mode)      //定义封装  Myopen   返回值MYFILE*     打开文件
{
    int fd = -1;
    int flag = 0;
    if(strcmp(mode,"w")==0)
    {	
	flag = O_CREAT | O_WRONLY | O_TRUNC;
	fd = open(path,flag,0666);
    }
    else if(strcmp(mode,"a")==0)
    {
	flag = O_CREAT | O_WRONLY | O_APPEND;
	fd = open(path,flag,0666);
    }
    else if(strcmp(mode,"r")==0)
    {
	flag = O_RDWR;
	fd = open(path,flag);
    }
    else
    {
	//TODO
    }
    
    if(fd < 0)  return NULL;
    return BuyFile(fd,flag);
}


void MyFclose(MyFile* file)     //这个参数只需要传文件   MyFile*    关文件
{
    if(file->fileno < 0)  return;
    MyFlush(file);
    close(file->fileno);
    free(file);
}


int MyFwrite(MyFile* file,void* str,int len)       //参数分别是 往哪个文件写，想写的字符串/字节流信息，长度
{
//写的本质是拷贝
    memcpy(file->outbuffer+file->bufferlen,str,len);
    file->bufferlen += len;
//写入之后需要刷新
   //尝试判断  是否满足刷新条件
   if((file->flush_method & LINE_FLUSH) && file->outbuffer[file->bufferlen-1] == '\n')
   {
	MyFlush(file);
   }  //这里不满足刷新条件就不会操作   满足了就会刷新
    return 0;
}


void MyFlush(MyFile* file)        //这是刷新
{
    if(file->bufferlen <= 0)  return;

//这里的write  把数据从用户拷贝到内核文件缓冲区中
    int n = write(file->fileno,file->outbuffer,file->bufferlen);
    (void)n;
//调用 fsync 把内核层面的数据刷新到外设
    fsync(file->fileno);    //就可以直接刷新   不需要结束的时候一总刷新  写一次刷一次
    file->bufferlen = 0;
}
